15. 설계의 의의와 설계를 대하는 방법

📌 Contents

📌 이 책은 어떤 설계를 주제로 집필한 것인가?

  • 소프트웨어에서 설계란, '어떤 소프트웨어의 품질 특성을 향상시키기 위한 구조를 만드는 것'이라고 말할 수 있음
  • 이 책에서는 유지 보수성 품질 특성을 향상시키기 위한 설계를 다뤄 왔음
  • 유지 보수성의 부가적인 특성에는 수정성이 있음
  • 수정성은 변경 용이성이라고도 부르며, 얼마나 쉽고 정확하게 코드를 변경할 수 있는지 나타내는 지표임
  • 이 책은 유지 보수성 중에서도 특히 변경 용이성을 목적으로 하는 설계 방법을 다루어 옴

📌 설계하지 않으면 개발 생산성이 저하된다

  • 변경하기 어렵고 버그가 생기기 쉬운 코드를 레거시 코드라고 함
  • 레거시 코드가 축적되어 있는 상태를 기술 부채라고 함
  • 변경 용이성 설계를 하지 않으면, 개발 생산성이 저하됨
  • 저하 요인으로는 크게 두 가지가 있음

요인 1: 버그가 발생하기 쉬운 구조

  • 응집도가 낮은 구조로 인해 사양 변경 시 수정 누락이 발생하기 쉬워지고, 결국 버그가 발생함
  • 코드를 이해하기 어려우므로 구현할 때 실수를 저지르기 쉬워지고, 결국 버그가 발생함
  • 잘못된 값이 들어오기 쉬워지고, 결국 버그가 발생함

요인 2: 가독성이 낮은 구조

  • 로직의 가독성이 낮아, 읽고 이해하는 데 시간이 오래 걸림
  • 관련된 로직이 이곳저곳에 흩어져 있어, 사양을 변경할 때 관련된 로직을 찾아서 돌아다니는 데 시간이 오래 걸림
  • 잘못된 값이 들어와서 버그가 발생했을 때, 잘못된 값의 출처를 추적하기 어려워짐

나무꾼의 딜레마

  • 도끼가 무뎌 나무가 잘 베이지 않지만, 나무 베는 것이 바빠 도끼를 갈 시간이 없는 상황
  • '나무를 자르는 시간'을 '로직을 구현하는 시간', '도끼의 날을 가는 시간'을 '설계하는 시간'으로 바꿔 생각해 볼 수 있음
  • 제대로 설계하지 않으면, 로직 변경과 디버그에 많은 시간을 소비하게 되고, 결국 설계할 시간 여유조차 없어지는 딜레마에 빠지게 됨

열심히 했지만 생산성이 나쁨

  • 개발 생산성이 나쁘면, '열심히 했다'는 느낌은 남지만, 생산성이 나빠 성과가 제대로 나지 않음
  • 열심히 했는데도 성과가 나지 않아 분노하고 스스로에게 실망하게 됨. 진정한 의미에서 '열심히 했다'고 할 수 있을까?
  • 성과를 내기 쉬운 구조를 설계하는 데 노력을 쏟지 않았다면, '열심히 했다'라고 이야기 하기 어려움

국가 규모의 경제 손실

  • 레거시 코드로 인한 생산성 저하로 발생하는 손실은 계속해서 축적됨
  • 이 손실은 레거시 코드의 양에 단순 비례하지 않음
  • 복잡하고 이해하기 힘든 로직이 있으면, 이로 인해 더 복잡하고 이해하기 힘든 로직이 만들어지기 때문임
  • 소스 코드가 점점 거대해지면, 이러한 문제가 점점 가속화 됨
  • 일본의 경제 산업성 발표 자료에 따르면, 2025년 이후 일본 내부의 기술 부채로 인한 경제적 손실이 12조 엔 정도 될 것이라고 함
  • 일본의 2021년 국가 예산이 142.5조 엔임
  • 설계를 소홀히 하고 매일 낮은 생산성을 방치한 결과, 국가 규모의 손실이 발생하고 있는 것임
  • 이러한 점에서 변경 용이성은 매우 중요한 품질 특성이라고 할 수 있음

📌 소프트웨어와 엔지니어의 성장 가능성

  • 변경 용이성을 높인다는 것은 소프트웨어의 성장 가능성을 높이는 것임
  • 소프트웨어의 성장 가능성을 높이는 것이 바로 이 책의 핵심 주제이자 의의임


  • '엔지니어'에게 '자산'이란 기술력임
  • 레거시 코드는 이러한 자산의 축적, 즉 기술력의 성장을 방해하는 무서운 존재임
    • 레거시 코드는 다음 사람으로 하여금 레거시 코드를 작성하게 하므로, 발전을 막음
    • 레거시 코드는 이미 균형이 깨져 있어서, 설계를 개선하기 힘들기 떄문에 프로젝트 납기 일정 등으로 설계 개선을 포기하기 되고, 결국에는 고품질 설계 구현 경험을 막음
    • 레거시 코드는 이해하는 데 시간이 오래 걸려, 시간을 낭비하게 만듦


  • 결국 레거시 코드는 기술 향상을 막고, 엔지니어에게 정말 중요한 자산이라 할 수 있는 기술력의 축적을 막음
  • 엔지니어에게 기술력은 곧 연봉과 직결됨
  • 레거시 코드는 엔지니어의 기술 성장도 막고, 연봉 인상도 막는 것임

📌 문제 해결하기

  1. 문제를 인식하지 못하면 설계에 대한 생각 자체가 떠오르지 않음
  2. 인지하기 쉬운 문제와 인지하기 어려운 문제가 있음
  3. 이상적인 형태를 알아야 문제를 인식할 수 있음
    • 문제는 항상 이상과 현실의 차이 때문에 발생함
    • 이상적인 설계와 현재 설계를 비교하면, 기술 부채를 인식할 수 있음
  4. 변경 용이성을 비교할 수 없는 딜레마
    • '변경 용이성을 고려해 설계한 미래'와 '설계를 타로 하지 않은 미래'를 동시에 관측할 수 있다면 변경 용이성 비교 가능함
    • 하지만 다른 미래를 오고 가거나 관측하는 기술이 없으므로, 불가능함

📌 코드의 좋고 나쁨을 판단하는 지표

  • '미래의 개발 생산성을 측정할 수 있는 방법'은 현재 시점에서는 없지만, '현재 소스 코드의 좋고 나쁨을 판단하는 지표(방법)'은 있음
  • 코드 복잡성과 가독성의 품질 지표를 코드 메트릭 또는 소프트웨어 메트릭이라고 부름

실행되는 코드의 줄 수

  • 주석을 제외하고, 실행되는 로직을 포함하는 코드의 줄 수를 의미
  • 줄 수가 많으면 많을수록, 너무 많은 일을 하고 있을 가능성이 높음
    • 루비의 코드 분석 라이브러리 RuboCop는 메서드 10줄 이내, 클래스 100줄 이내를 '적절한 코드 줄 수의 상한'으로 판단
  • 줄 수가 너무 많으면 '메서드와 클래스 분할'을 검토해 보기

순환 복잡도

  • 코드의 구조적인 복잡함을 나타내는 지표
  • 조건 분기, 반복 처리, 중첩이 많아지면 복잡도가 커짐
  • 조기 리턴, 전략 패턴, 일급 컬렉션 등의 테크닉을 활용하면 복잡도를 줄일 수 있음
  • 데이터 클래스는 로직이 따로 없어 복잡도가 0이지만, 다른 클래스의 복잡도에 영향을 줄 수 있으므로 주의해야 함

응집도

  • 모듈 내부에서 데이터와 로직이 관련되어 있는 정도를 나타내는 지표
  • 클래스 내부에서 데이터와 로직의 관계가 얼마나 강한지 나타내는 지표
  • 인스턴스 변수와 그 인스턴스 변수를 사용하는 로직이 같은 클래스에 구현되어 있으면, 응집도가 높다고 할 수 있음

결합도

  • 모듈 간의 의존도를 나타내는 지표
  • 어떤 클래스가 호출하는 다른 클래스의 수
  • 의존하고 있는 클래스가 많으면 많을수록, 즉 결합도가 높으면 높을수록 더 넓은 범위를 고려해야 하므로, 유지 보수와 사양 변경이 어려움

청크

  • 코드 메트릭은 아님
  • 인간의 단기 기억은 한번에 4+-1개의 개념 정도만 파악할 수 있다고 함
    • 이 숫자를 매지컬 넘버 4라고 부름
  • 기억할 수 있는 정보 덩어리의 단위를 청크라고 함
  • 클래스를 설계할 때도 매지컬 넘버 4를 염두에 두고 뇌가 쉽게 받아드릴 수 있는 구조인지 생각해 보기
    • 클래스에서 다루는 개념이 4+-1개 정도가 되도록 설계하기

📌 코드 분석을 지원하는 다양한 도구

Code Climate Quality

  • 깃허브와 연동하면 리포지터리에 저장된 코드의 품질 점수를 자동으로 계산해줌
  • 다양한 분석 기능을 제공

Understand

  • 코드 줄 수, 복잡도, 응집도, 결합도 이외에도 다양한 관점의 메트릭을 계측할 수 있음
  • 클래스와 메서드 사이의 의존 관계를 시각화하는 그래픽 뷰라는 기능도 갖고 있어서, 사양 변경 시 영향 범위를 파악할 때도 편리함
  • 또한 이를 통해 영향 범위를 줄일 수도 있음

Visual Studio

  • IDE
  • 코드 메트릭 계산 기능을 사용할 수 있음
  • 실행 가능한 코드의 줄 수, 복잡도, 결합도를 분석해 줌
  • 전체적인 부채 정도를 나타내는 유지 보수 용이성 인덱스(유지 관리 인덱스)를 계산해 줌
  • 이러한 지표를 메서드, 클래스, 패키지 단위로 계산할 수도 있음

📌 설계 대상과 비용 대비 효과

  • 사양 변경도 없는데, 비용을 들여 변경 용이성을 높이는 것은 낭비
    • 비용 대비 효과가 매우 낮을 것이기 때문
  • 비용 대비 효과가 높은 부분을 노려야 함

파레토의 법칙 (80:20의 법칙)

  • 전체 결과의 80%가 전체 원인의 20%에서 일어난다는 법칙
    • '매출의 80%는 전체 상품 중 20%의 상품이 만들어 낸다'
    • '소프트웨어의 처리 시간 중 80%는 소스 코드 전체의 20%가 차지한다'
  • 소프트웨어의 기능 전체 중에서 중점적으로 사용되는 기능은 1/3 정도밖에 되지 않는다고 함
  • 사양이 자주 바뀌는 곳도 일부에 한정되어 있음
  • 기능의 중요성, 사양 변경 빈도 모두 파레토의 법칙에 해당
  • 중요하고 사양 변경이 빈번한 곳의 설계를 개선하면, 비용 대비 효과가 높을 것임

코어 도메인: 서비스의 중심 영역

  • 서비스에서 중심이 되는 비즈니스 영역을 코어 도메인이라고 함 (도메인 주도 설계 17.1.11절)
  • 코어 도메인은 다음과 같음
    • 시스템에서 가장 큰 가치를 창출하는 곳
    • 가치 있고 중요하고 비용 대비 효과가 가장 큰 곳
    • 경쟁 우위에 있고, 차별점을 만들며, 비즈니스 우위를 만들 수 있는 곳
  • 설계에 비용을 투자해야 하는 곳, 비용 대비 효과가 큰 곳이라고 할 수 있음

중점 설계 대상 선정에는 비즈니스 지식이 필요함

  • 설계 비용 대비 효과를 높이려면, 중점적인 설계 대상을 선정할 수 있어야 함
  • 대상을 잘 선정하려면, 서비스가 해결하고 싶은 고객 과제가 무엇인지, 서비스의 본질이 무엇인지 볼 수 있는 능력이 필요함
  • 즉, 서비스와 관련된 비즈니스 지식이 필요함
  • 구조의 좋고 나쁨에만 주목하면, 설계가 비즈니스 전략을 제대로 뒷받침하지 못할 수 있음
  • 성장 가능성을 높이기 위한 최적의 설계와 비즈니스 지식은 떼려야 뗄 수 없는 관계임

📌 시간을 다스리는 능력자 되기

  • 현재의 설계 품질은 미래에 소비할 시간에 직접적인 영향을 줌
  • 시스템을 개발하는 엔지니어는 내부 구조를 머릿속에 그릴 수 있음
  • 설계의 본질을 볼 수 있는 엔지니어는 악마의 정체를 꿰뚫어 볼 수 있는 눈, 즉 레거시 코드를 머릿속에 그릴 수 잇는 능력을 갖고 있음
  • 머릿속에 그리는 능력과 설계 능력을 활용하면 미래의 시간을 조종할 수 있음

results matching ""

    No results matching ""